<template>
  <div style="padding: 20px;">
    <a-upload-dragger
      v-show="showUpload"
      :accept="accept"
      :customRequest="customRequest"
      :showUploadList="false"
      @reject="rejectNotAccept"
    >
      <div style="padding: 45px;">
        <p>
          <a-icon type="plus" style="color: #1890ff;"/>
        </p>
        <p>点击或将文件拖拽到这里上传</p>
        <p style="font-size: 12px; color: rgba(0, 0, 0, 0.4)">
          支持Excel、CSV表格文件，及.zip压缩的shapefile文件
        </p>
        <p style="font-size: 12px; color: rgba(0, 0, 0, 0.4);">
          （支持断点续传）
        </p>
        <p v-if="errorTypeStatus" style="font-size: 12px;color: red;margin-top: 10px;">
          {{ errorTypeText }}
        </p>
      </div>
    </a-upload-dragger>

    <div v-show="!showUpload" style="width: 100%;padding: 45px 20px;border: 1px dashed #d9d9d9;border-radius: 2px;background: #fafafa;">
      <a-progress :percent="percent" :status="percentStatus"/>
    </div>

  </div>
</template>

<script>
import md5 from 'js-md5'
import { checkFileChunk, doUpload } from '@/api/modular/main/baseIndex/fileChunkUpload'
import { concurrentExecution } from '@/utils/util'
export default {
  name: 'upload',
  data() {
    return {
      accept: '.zip,.xls,.xlsx,.csv',
      concurrent: 5,
      chunkCount: 0,
      chunkSize: 2 * 1024 * 1024, // 2MB一片
      file: null,
      fileType: '',
      fileMD5: '',
      uploaded: [], // 已经上传的
      chunkList: [], // 分片列表
      percent: 0,
      percentStatus: 'active',
      showUpload: true,
      errorTypeText: '',
      errorTypeStatus: false
    }
  },
  methods: {
    md5,
    customRequest(data) {
      const _that = this
      this.file = data.file
      console.log(this.file)
      this.fileType = this.file.name.substring(this.file.name.lastIndexOf('.') + 1, this.file.name.length)
      this.chunkCount = Math.ceil(this.file.size / this.chunkSize) // 总片数
      this.chunkList = [] // 分片列表
      this.uploaded = []
      this.showUpload = false
      this.errorTypeStatus = false
      console.log('获取文件的MD5值')
      const fileReaderInstance = new FileReader()
      fileReaderInstance.readAsBinaryString(this.file)
      fileReaderInstance.addEventListener('load', e => {
        console.log('e:', e)
        const fileBolb = e.target.result
        _that.fileMD5 = this.md5(fileBolb)
        console.log('fileMD5:', _that.fileMD5)
        const form = new FormData()
        form.append('filename', _that.file.name)
        form.append('identifier', _that.fileMD5)
        form.append('objectType', _that.fileType)
        form.append('chunkNumber', 1)
        checkFileChunk(form).then(res => {
          console.log(res)
          if (res.success) {
            if (res.data.skipUpload) {
              this.$message.warning('文件已被上传')
            } else {
              if (res.data.uploaded && res.data.uploaded.length !== 0) {
                _that.uploaded = [].concat(res.data.uploaded)
              }
              console.log('已上传的分片：', _that.uploaded)
              if (_that.chunkCount === 1 || _that.concurrent === 1) {
                console.log('顺序上传')
                _that.sequentialUpload(0)
              } else {
                console.log('并发上传')
                _that.concurrentUpload()
              }
            }
          }
        }).catch((e) => {
          console.error('文件合并错误:', e)
        })
      })
    },
    /**
     * 顺序上传
     */
    sequentialUpload(currentChunk) {
      const _that = this
      const { chunkCount } = this
      const { chunk } = this.getChunkInfo(this.file, currentChunk, this.chunkSize)
      const chunkInfo = {
        chunk,
        currentChunk,
        chunkCount
      }
      const sd = parseInt((chunkInfo.currentChunk / chunkInfo.chunkCount) * 100)
      _that.percent = sd
      console.log('上传进度：', sd)
      console.log('当前上传分片：', currentChunk)
      const index = currentChunk + 1
      if (this.uploaded.indexOf(index + '') > -1) {
        console.log('分片【' + currentChunk + '】已上传')
        this.sequentialUpload(currentChunk + 1)
      } else {
        const uploadData = this.createUploadData(chunkInfo)
        doUpload(uploadData).then(res => {
          if (res.success) {
            _that.uploaded.push(chunkInfo.currentChunk + 1)
            if (_that.uploaded.length === chunkInfo.chunkCount) {
              console.log('全部完成')
              _that.percent = 100
              _that.percentStatus = 'success'
            } else {
              _that.sequentialUpload(currentChunk + 1)
            }
          } else {
            _that.percentStatus = 'exception'
          }
        }).catch(() => {
          _that.percentStatus = 'exception'
        })
      }
    },
    /**
     * 并发上传
     */
    concurrentUpload() {
      for (let i = 0; i < this.chunkCount; i++) {
        this.chunkList.push(Number(i))
      }
      console.log('需要上传的分片列表：', this.chunkList)
      const _that = this
      concurrentExecution(this.chunkList, this.concurrent, (curItem) => {
          return new Promise((resolve, reject) => {
            const { chunkCount } = this
            const { chunk } = _that.getChunkInfo(_that.file, curItem, _that.chunkSize)
            const chunkInfo = {
              chunk,
              currentChunk: curItem,
              chunkCount
            }
            const sd = parseInt((chunkInfo.currentChunk / chunkInfo.chunkCount) * 100)
            _that.percent = sd
            console.log('上传进度：', sd)
            console.log('当前上传分片：', chunkInfo.currentChunk)
            const index = chunkInfo.currentChunk + 1
            if (_that.uploaded.indexOf(index + '') === -1) {
              const uploadData = _that.createUploadData(chunkInfo)
              doUpload(uploadData).then(res => {
                if (res.success) {
                  _that.uploaded.push(chunkInfo.currentChunk + 1)
                  console.log('已经上传完成的分片：', _that.uploaded)
                  // 判断是否全部上传完
                  if (_that.uploaded.length === chunkInfo.chunkCount) {
                    _that.percent = 100
                    _that.percentStatus = 'success'
                    console.log('上传进度：', 100)
                  }
                  resolve()
                } else {
                  reject(res)
                  _that.percentStatus = 'exception'
                  console.error(res.message)
                }
              }).catch(err => {
                reject(err)
                _that.percentStatus = 'exception'
                console.error(err)
              })
            } else {
              console.log('分片【' + chunkInfo.currentChunk + '】已上传')
              resolve()
            }
          })
      }).then(res => {
        console.log('finish', res)
      })
    },
    /**
     * 获取每一个分片的详情
     */
    getChunkInfo(file, currentChunk, chunkSize) {
      const start = currentChunk * chunkSize
      const end = Math.min(file.size, start + chunkSize)
      const chunk = file.slice(start, end)
      return {
        start,
        end,
        chunk
      }
    },
    createUploadData(chunkInfo) {
      const fetchForm = new FormData()
      fetchForm.append('identifier', this.fileMD5)
      fetchForm.append('chunkNumber', chunkInfo.currentChunk + 1)
      fetchForm.append('chunkSize', this.chunkSize)
      fetchForm.append('currentChunkSize', chunkInfo.chunk.size)
      const chunkfile = new File([chunkInfo.chunk], this.file.name)
      fetchForm.append('file', chunkfile)
      fetchForm.append('filename', this.file.name)
      fetchForm.append('totalChunks', chunkInfo.chunkCount)
      fetchForm.append('totalSize', this.file.size)
      fetchForm.append('objectType', this.fileType)
      return fetchForm
    },
    rejectNotAccept(fileList) {
      console.log(fileList)
      if (fileList && fileList.length > 0) {
        const file = fileList[0]
        const type = file.type
        this.errorTypeText = '不支持' + type + '类型的文件'
        this.errorTypeStatus = true
      }
    }
  }
}
</script>

<style scoped>

</style>
